# Handles drawing the map and placing objects on it.

import libtcodpy as libtcod
from Tile import Tile
from GameObject import GameObject
from GameObject import Fighter
from GameObject import BasicMonster
import Helpers

class Rect:
    def __init__(self, x, y, w, h):
        self.x1 = x
        self.x2 = x + w
        self.y1 = y
        self.y2 = y + h
        
    def center(self):
        center_x = (self.x1 + self.x2) / 2
        center_y = (self.y1 + self.y2) / 2
        return (center_x, center_y)
    
    def intersect(self, other):
        return (self.x1 <= other.x2 and self.x2 >= other.x1 and
                self.y1 <= other.y2 and self.y2 >= other.y1) #change last to other y 2 for interesting effect
        
class Map:
    def __init__(self, gamestate):
        self.MAP_WIDTH = 80
        self.MAP_HEIGHT = 45
        self.ROOM_MAX_SIZE = 18
        self.ROOM_MIN_SIZE = 6
        self.MAX_ROOMS = 30
        self.MAX_ROOM_MONSTERS = 3
        
        self.color_empty_map = libtcod.Color(10,10,10)
        self.color_dark_wall = libtcod.Color(26, 24, 21)
        self.color_light_wall = libtcod.Color(130, 110, 50)
        self.color_dark_ground = libtcod.Color(43, 39, 35)
        self.color_light_ground = libtcod.Color(200, 180, 50)
        
        self.gamestate = gamestate
        self.map = []
        self.gen_map()
    
    def gen_map(self):
        self.map = [[Tile(True) for y in range(self.MAP_HEIGHT)] for x in range(self.MAP_WIDTH)]
        
        rooms = []
        num_rooms = 0
        
        for r in range(self.MAX_ROOMS):
            w = libtcod.random_get_int(0, self.ROOM_MIN_SIZE, self.ROOM_MAX_SIZE)
            h = libtcod.random_get_int(0, self.ROOM_MIN_SIZE, self.ROOM_MAX_SIZE)
            x = libtcod.random_get_int(0, 0, self.MAP_WIDTH-w-1)
            y = libtcod.random_get_int(0, 0, self.MAP_HEIGHT-h-1)
            
            new_room = Rect(x, y, w, h)
            failed = False
            for other_room in rooms:
                if new_room.intersect(other_room):
                    failed = True
                    break
            if not failed:
                self.create_room(new_room)
                self.place_objects(new_room)
                (new_x, new_y) = new_room.center()
                
                if num_rooms == 0:
                    self.gamestate.player.x = new_x
                    self.gamestate.player.y = new_y
                    # dont add the tunnels for an easy boss level type thing
                else:
                    (prev_x, prev_y) = rooms[num_rooms-1].center()
                    if libtcod.random_get_int(0, 0, 1) == 1:
                        self.create_h_tunnel(prev_x, new_x, prev_y)  #some interesting areas can be made by messing with these
                        self.create_v_tunnel(prev_y, new_y, new_x)
                    else:
                        self.create_v_tunnel(prev_y, new_y, prev_x)
                        self.create_h_tunnel(prev_x, new_x, new_y)
                rooms.append(new_room)
                num_rooms += 1
                    
        return map
    
    def create_room(self, room):
        for x in range(room.x1 + 1, room.x2):
            for y in range(room.y1 + 1, room.y2):
                self.map[x][y].blocked = False
                self.map[x][y].block_sight = False
    
    def create_h_tunnel(self, x1, x2, y):
        for x in range(min(x1, x2), max(x1, x2) + 1):
            self.map[x][y].blocked = False
            self.map[x][y].block_sight = False
            
    def create_v_tunnel(self, y1, y2, x):
        for y in range(min(y1, y2), max(y1, y2) + 1):
            self.map[x][y].blocked = False
            self.map[x][y].block_sight = False
            
    def place_objects(self, room):
        num_monsters = libtcod.random_get_int(0, 0, self.MAX_ROOM_MONSTERS)
     
        if libtcod.random_get_int(0, 0, 100) < 30: #20% chance of spawning a potion
            x = libtcod.random_get_int(0, room.x1, room.x2)
            y = libtcod.random_get_int(0, room.y1, room.y2)
            potion = GameObject(self.gamestate, x, y, 'p', "potion", libtcod.blue, blocks=False, use_func=Helpers.Helper.potion)
            if not self.is_blocked(x,y):
                self.gamestate.game_objects.append(potion)
            
        for i in range(num_monsters):
            x = libtcod.random_get_int(0, room.x1, room.x2)
            y = libtcod.random_get_int(0, room.y1, room.y2)
            
            ai_component = BasicMonster()
            
            if libtcod.random_get_int(0, 0, 100) < 80:  #80% chance of getting an orc
                orc_fighter_component = Fighter(hp=10, defense=0, power=3, death_func=Helpers.Helper.monster_death)
                monster = GameObject(self.gamestate, x, y, 'o', "orc", 
                                     libtcod.desaturated_green, blocks=True, fighter=orc_fighter_component,
                                     ai=ai_component)
            else:
                troll_fighter_component = Fighter(hp=16, defense=1, power=4, death_func=Helpers.Helper.monster_death)
                monster = GameObject(self.gamestate, x, y, 'T', "troll", libtcod.darker_green, blocks=True,
                                     fighter=troll_fighter_component, ai=ai_component)
                
            if not self.is_blocked(x,y):
                self.gamestate.game_objects.append(monster)
                
    def is_blocked(self, x, y):
        if self.map[x][y].blocked:
            return True
        
        for game_object in self.gamestate.game_objects:
            if game_object.blocks and game_object.x == x and game_object.y == y:
                return True
        
        return False